home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / c / tox.lha / tox / tox.c < prev    next >
C/C++ Source or Header  |  2002-10-20  |  17KB  |  600 lines

  1. /*-------------------------------------------------------------------------
  2.  * tox - an XML tokenizer
  3.  *
  4.  * Copyright (c) 2000 Eckhart Köppen
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Library General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Library General Public
  17.  * License along with this library; if not, write to the
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA 02111-1307, USA.
  20.  *-----------------------------------------------------------------------*/
  21.  
  22. /* $Id: tox.c,v 1.19 2002/05/01 03:14:30 koeppen Exp $ */
  23.  
  24. #include "tox.h"
  25.  
  26. #define TYPE_RANGE       0
  27. #define TYPE_EXACT       1
  28. #define TYPE_SPECIAL     2
  29. #define TYPE_END         3
  30.  
  31. #define SPECIAL_SKIP_DTD 0
  32.  
  33. #define RANGE_LETTER     0
  34. #define RANGE_CHAR       1
  35. #define RANGE_WS         2
  36. #define RANGE_NAMECHAR   3
  37. #define RANGE_HEX        4
  38. #define RANGE_DEC        5
  39.  
  40. typedef unsigned short char_t;
  41.  
  42. typedef struct
  43. {
  44.     unsigned int accept_type;
  45.     char_t accept_value;
  46.     int next_state;
  47.     unsigned char action;
  48. } state_def;
  49.  
  50. typedef struct
  51. {
  52.     char_t start;
  53.     char_t end;
  54. } char_range;
  55.  
  56. const char_range range_table[][12] = {
  57.     /* letter */
  58.     {
  59.      {0x0041, 0x005A},
  60.      {0x0061, 0x007A},
  61.      {0x00C0, 0x00D6},
  62.      {0x00D8, 0x00F6},
  63.      {0x00F8, 0x00FF}
  64.      },
  65.     /* character */
  66.     {
  67.      {0x0009, 0x0009},
  68.      {0x000A, 0x000A},
  69.      {0x000D, 0x000D},
  70.      {0x0020, 0x00FF}
  71.      },
  72.     /* whitespace */
  73.     {
  74.      {0x0009, 0x0009},
  75.      {0x000A, 0x000A},
  76.      {0x000D, 0x000D},
  77.      {0x0020, 0x0020},
  78.      },
  79.     /* name character */
  80.     {
  81.      {'.', '.'},
  82.      {'-', '-'},
  83.      {'_', '_'},
  84.      {':', ':'},
  85.      {0x0030, 0x0039},
  86.      {0x0041, 0x005A},
  87.      {0x0061, 0x007A},
  88.      {0x00B7, 0x00B7},
  89.      {0x00C0, 0x00D6},
  90.      {0x00D8, 0x00F6},
  91.      {0x00F8, 0x00FF}
  92.      },
  93.     /* hex numbers */
  94.     {
  95.      {'0', '9'},
  96.      {'a', 'f'},
  97.      {'A', 'F'}
  98.      },
  99.     /* digits */
  100.     {
  101.      {'0', '9'}
  102.      },
  103. };
  104.  
  105. #define ACTION_PUMP_START        1
  106. #define ACTION_TAGNAME_END       2
  107. #define ACTION_ATTRNAME_END      4
  108. #define ACTION_ATTRVAL_END       8
  109. #define ACTION_WORD_END         16
  110. #define ACTION_WS_END           32
  111.  
  112. const state_def state_table[][7] = {
  113.     /*  0: STATE_CONTENT */
  114.     {
  115.      {TYPE_EXACT, (char_t) '<', STATE_STARTTAG_START, 0},
  116.      {TYPE_EXACT, (char_t) '&', STATE_REF_START, 0},
  117.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_WS_CONTENT, ACTION_PUMP_START},
  118.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_WORD_CONTENT, ACTION_PUMP_START},
  119.      {TYPE_END, 0, STATE_ERROR, 0}
  120.      },
  121.     /*  1: STATE_STARTTAG_START */
  122.     {
  123.      {TYPE_EXACT, (char_t) '/', STATE_ENDTAG_START, ACTION_PUMP_START},
  124.      {TYPE_EXACT, (char_t) '_', STATE_STARTTAG_NAME, ACTION_PUMP_START},
  125.      {TYPE_EXACT, (char_t) ':', STATE_STARTTAG_NAME, ACTION_PUMP_START},
  126.      {TYPE_EXACT, (char_t) '?', STATE_PI, 0},
  127.      {TYPE_EXACT, (char_t) '!', STATE_MARKUPDECL_START, 0},
  128.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_STARTTAG_NAME, ACTION_PUMP_START},
  129.      {TYPE_END, 0, STATE_ERROR, 0}
  130.      },
  131.     /*  2: STATE_REF_START */
  132.     {
  133.      {TYPE_EXACT, (char_t) '_', STATE_REF_NAME, 0},
  134.      {TYPE_EXACT, (char_t) ':', STATE_REF_NAME, 0},
  135.      {TYPE_EXACT, (char_t) '#', STATE_REF_NUMBER, 0},
  136.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_REF_NAME, 0},
  137.      {TYPE_END, 0, STATE_ERROR, 0}
  138.      },
  139.     /*  3: STATE_CHARDATA */
  140.     {
  141.      {TYPE_END, 0, STATE_ERROR, 0}
  142.      },
  143.     /*  4: STATE_ENDTAG_START */
  144.     {
  145.      {TYPE_EXACT, (char_t) '_', STATE_ENDTAG_NAME, 0},
  146.      {TYPE_EXACT, (char_t) ':', STATE_ENDTAG_NAME, 0},
  147.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ENDTAG_NAME, 0},
  148.      {TYPE_END, 0, STATE_ERROR, 0}
  149.      },
  150.     /*  5: STATE_STARTTAG_NAME */
  151.     {
  152.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_STARTTAG_NAME, 0},
  153.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_STARTTAG_NAMEEND, ACTION_TAGNAME_END},
  154.      {TYPE_EXACT, (char_t) '/', STATE_EMPTYTAG_END, 0},
  155.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, ACTION_TAGNAME_END},
  156.      {TYPE_END, 0, STATE_ERROR, 0}
  157.      },
  158.     /*  6: STATE_REF_NAME */
  159.     {
  160.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_REF_NAME, 0},
  161.      {TYPE_EXACT, (char_t) ';', STATE_CONTENT, 0},
  162.      {TYPE_END, 0, STATE_ERROR, 0}
  163.      },
  164.     /*  7: STATE_ENDTAG_NAME */
  165.     {
  166.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ENDTAG_NAME, 0},
  167.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ENDTAG_NAMEEND, ACTION_TAGNAME_END},
  168. /*     {TYPE_EXACT, (char_t) '/', STATE_EMPTYTAG_END, 0}, ??? */
  169.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, ACTION_TAGNAME_END},
  170.      {TYPE_END, 0, STATE_ERROR, 0}
  171.      },
  172.     /*  8: STATE_STARTTAG_NAMEEND */
  173.     {
  174.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_STARTTAG_NAMEEND,  0},
  175.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT,  0},
  176.      {TYPE_EXACT, (char_t) '/', STATE_EMPTYTAG_END, 0},
  177.      {TYPE_EXACT, (char_t) '_', STATE_ATTR_NAME, ACTION_PUMP_START},
  178.      {TYPE_EXACT, (char_t) ':', STATE_ATTR_NAME, ACTION_PUMP_START},
  179.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ATTR_NAME, ACTION_PUMP_START},
  180.      {TYPE_END, 0, STATE_ERROR, 0}
  181.      },
  182.     /*  9: STATE_ENDTAG_NAMEEND */
  183.     {
  184.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ENDTAG_NAMEEND, 0},
  185.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  186.      {TYPE_END, 0, STATE_ERROR, 0}
  187.      },
  188.     /* 10: STATE_ATTR_NAME */
  189.     {
  190.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ATTR_NAME, 0},
  191.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ATTR_NAMEEND, ACTION_ATTRNAME_END},
  192.      {TYPE_EXACT, (char_t) '=', STATE_ATTR_VALSTART, ACTION_ATTRNAME_END},
  193.      {TYPE_END, 0, STATE_ERROR, 0}
  194.      },
  195.     /* 11: STATE_ATTR_NAMEEND */
  196.     {
  197.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ATTR_NAMEEND, 0},
  198.      {TYPE_EXACT, (char_t) '=', STATE_ATTR_VALSTART, 0},
  199.      {TYPE_END, 0, STATE_ERROR, 0}
  200.      },
  201.     /* 12: STATE_ATTR_VALSTART */
  202.     {
  203.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ATTR_VALSTART, 0},
  204.      {TYPE_EXACT, (char_t) '"', STATE_ATTR_VALDQUOT, 0},
  205.      {TYPE_EXACT, (char_t) '\'', STATE_ATTR_VALSQUOT, 0},
  206.      {TYPE_END, 0, STATE_ERROR, 0}
  207.      },
  208.     /* 13: STATE_ATTR_VALDQUOT */
  209.     {
  210.      {TYPE_EXACT, (char_t) '"', STATE_STARTTAG_NAMEEND, ACTION_ATTRVAL_END},
  211.      {TYPE_EXACT, (char_t) '<', STATE_ERROR, 0},
  212.      {TYPE_EXACT, (char_t) '&', STATE_ATTR_VALDQUOT_REF, ACTION_PUMP_START},
  213.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_ATTR_VALDQUOT, ACTION_PUMP_START},
  214.      {TYPE_END, 0, STATE_ERROR, 0}
  215.      },
  216.     /* 14: STATE_EMPTYTAG_END */
  217.     {
  218.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  219.      {TYPE_END, 0, STATE_ERROR, 0}
  220.     },
  221.     /* 15: STATE_ATTR_VALDQUOT_REF */
  222.     {
  223.      {TYPE_EXACT, (char_t) '_', STATE_ATTR_VDQ_REFNAME, 0},
  224.      {TYPE_EXACT, (char_t) ':', STATE_ATTR_VDQ_REFNAME, 0},
  225.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ATTR_VDQ_REFNAME, 0},
  226.      {TYPE_END, 0, STATE_ERROR, 0}
  227.      },
  228.     /* 16: STATE_ATTR_VDQ_REFNAME */
  229.     {
  230.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ATTR_VDQ_REFNAME, 0},
  231.      {TYPE_EXACT, (char_t) ';', STATE_ATTR_VALDQUOT, 0},
  232.      {TYPE_END, 0, STATE_ERROR, 0}
  233.      },
  234.     /* 17: STATE_ATTR_VALSQUOT */
  235.     {
  236.      {TYPE_EXACT, (char_t) '\'', STATE_STARTTAG_NAMEEND, ACTION_ATTRVAL_END},
  237.      {TYPE_EXACT, (char_t) '<', STATE_ERROR, 0},
  238.      {TYPE_EXACT, (char_t) '&', STATE_ATTR_VALSQUOT_REF, ACTION_PUMP_START},
  239.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_ATTR_VALSQUOT, ACTION_PUMP_START},
  240.      {TYPE_END, 0, STATE_ERROR, 0}
  241.      },
  242.     /* 18: STATE_ATTR_VALSQUOT_REF */
  243.     {
  244.      {TYPE_EXACT, (char_t) '_', STATE_ATTR_VSQ_REFNAME, 0},
  245.      {TYPE_EXACT, (char_t) ':', STATE_ATTR_VSQ_REFNAME, 0},
  246.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ATTR_VSQ_REFNAME, 0},
  247.      {TYPE_END, 0, STATE_ERROR, 0}
  248.      },
  249.     /* 19: STATE_ATTR_VSQ_REFNAME */
  250.     {
  251.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ATTR_VSQ_REFNAME, 0},
  252.      {TYPE_EXACT, (char_t) ';', STATE_ATTR_VALSQUOT, 0},
  253.      {TYPE_END, 0, STATE_ERROR, 0}
  254.      },
  255.     /* 20: STATE_DTD_START */
  256.     {
  257.      {TYPE_SPECIAL, (char_t) SPECIAL_SKIP_DTD, STATE_CONTENT, 0},
  258.      {TYPE_END, 0, STATE_ERROR, 0}
  259.      },
  260.     /* 21: STATE_MARKUPDECL_START */
  261.     {
  262.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT_START_1ST, 0},
  263.      {TYPE_EXACT, (char_t) 'D', STATE_DOCTYPE_D, 0},
  264.      {TYPE_EXACT, (char_t) '[', STATE_CDATA_BRACKET, 0},
  265.      {TYPE_END, 0, STATE_ERROR, 0}
  266.      },
  267.     /* 22: STATE_CDATA */
  268.     {
  269.      {TYPE_EXACT, (char_t) ']', STATE_CDATA_1ST_BRACKET, 0},
  270.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_CDATA, 0},
  271.      {TYPE_END, 0, STATE_ERROR, 0}
  272.      },
  273.     /* 23: STATE_CDATA_1ST_BRACKET */
  274.     {
  275.      {TYPE_EXACT, (char_t) ']', STATE_CDATA_2ND_BRACKET, 0},
  276.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_CDATA, 0},
  277.      {TYPE_END, 0, STATE_ERROR, 0}
  278.      },
  279.     /* 24: STATE_CDATA_2ND_BRACKET */
  280.     {
  281.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  282.      {TYPE_EXACT, (char_t) ']', STATE_CDATA_2ND_BRACKET, 0},
  283.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_CDATA, 0},
  284.      {TYPE_END, 0, STATE_ERROR, 0}
  285.      },
  286.     /* 25: STATE_PI */
  287.     {
  288.      {TYPE_EXACT, (char_t) '?', STATE_PI_END_QMARK, 0},
  289.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_PI, 0},
  290.      {TYPE_END, 0, STATE_ERROR, 0}
  291.      },
  292.     /* 26: STATE_PI_END_QMARK */
  293.     {
  294.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  295.      {TYPE_EXACT, (char_t) '?', STATE_PI_END_QMARK, 0},
  296.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_PI, 0},
  297.      {TYPE_END, 0, STATE_ERROR, 0}
  298.      },
  299.     /* 27: STATE_COMMENT */
  300.     {
  301.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT_1ST_DASH, 0},
  302.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_COMMENT, 0},
  303.      {TYPE_END, 0, STATE_ERROR, 0}
  304.      },
  305.     /* 28: STATE_COMMENT_1ST_DASH */
  306.     {
  307.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT_2ND_DASH, 0},
  308.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_COMMENT, 0},
  309.      {TYPE_END, 0, STATE_ERROR, 0}
  310.      },
  311.     /* 29: STATE_COMMENT_2ND_DASH */
  312.     {
  313.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  314.      {TYPE_END, 0, STATE_ERROR, 0}
  315.      },
  316.     /* 30: STATE_REF_NUMBER */
  317.     {
  318.      {TYPE_EXACT, (char_t) 'x', STATE_REF_HEX_NUMBER_1, 0},
  319.      {TYPE_RANGE, (char_t) RANGE_DEC, STATE_REF_DEC_NUMBER, 0},
  320.      {TYPE_END, 0, STATE_ERROR, 0}
  321.      },
  322.     /* 31: STATE_REF_HEX_NUMBER_1 */
  323.     {
  324.      {TYPE_RANGE, (char_t) RANGE_HEX, STATE_REF_HEX_NUMBER, 0},
  325.      {TYPE_END, 0, STATE_ERROR, 0}
  326.      },
  327.     /* 32: STATE_REF_HEX_NUMBER */
  328.     {
  329.      {TYPE_RANGE, (char_t) RANGE_HEX, STATE_REF_HEX_NUMBER, 0},
  330.      {TYPE_EXACT, (char_t) ';', STATE_CONTENT, 0},
  331.      {TYPE_END, 0, STATE_ERROR, 0}
  332.      },
  333.     /* 33: STATE_REF_DEC_NUMBER */
  334.     {
  335.      {TYPE_RANGE, (char_t) RANGE_DEC, STATE_REF_DEC_NUMBER, 0},
  336.      {TYPE_EXACT, (char_t) ';', STATE_CONTENT, 0},
  337.      {TYPE_END, 0, STATE_ERROR, 0}
  338.      },
  339.     /* 34: STATE_WS_CONTENT */
  340.     {
  341.      {TYPE_EXACT, (char_t) '<', STATE_STARTTAG_START, ACTION_WS_END},
  342.      {TYPE_EXACT, (char_t) '&', STATE_REF_START, ACTION_WS_END},
  343.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_WS_CONTENT, 0},
  344.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_WORD_CONTENT, ACTION_PUMP_START | ACTION_WS_END},
  345.      {TYPE_END, 0, STATE_ERROR, 0}
  346.      },
  347.     /* 35: STATE_WORD_CONTENT */
  348.     {
  349.      {TYPE_EXACT, (char_t) '<', STATE_STARTTAG_START, ACTION_WORD_END},
  350.      {TYPE_EXACT, (char_t) '&', STATE_REF_START, ACTION_WORD_END},
  351.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_WS_CONTENT, ACTION_PUMP_START | ACTION_WORD_END},
  352.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_WORD_CONTENT, 0},
  353.      {TYPE_END, 0, STATE_ERROR, 0}
  354.      },
  355.     /* 36: STATE_COMMENT_START_1ST */
  356.     {
  357.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT, 0},
  358.      {TYPE_END, 0, STATE_ERROR, 0}
  359.      },
  360.     /* 37: STATE_DOCTYPE_D */
  361.     {
  362.      {TYPE_EXACT, (char_t) 'O', STATE_DOCTYPE_O, 0},
  363.      {TYPE_END, 0, STATE_ERROR, 0}
  364.      },
  365.     /* 38: STATE_DOCTYPE_O */
  366.     {
  367.      {TYPE_EXACT, (char_t) 'C', STATE_DOCTYPE_C, 0},
  368.      {TYPE_END, 0, STATE_ERROR, 0}
  369.      },
  370.     /* 39: STATE_DOCTYPE_C */
  371.     {
  372.      {TYPE_EXACT, (char_t) 'T', STATE_DOCTYPE_T, 0},
  373.      {TYPE_END, 0, STATE_ERROR, 0}
  374.      },
  375.     /* 40: STATE_DOCTYPE_T */
  376.     {
  377.      {TYPE_EXACT, (char_t) 'Y', STATE_DOCTYPE_Y, 0},
  378.      {TYPE_END, 0, STATE_ERROR, 0}
  379.      },
  380.     /* 41: STATE_DOCTYPE_Y */
  381.     {
  382.      {TYPE_EXACT, (char_t) 'P', STATE_DOCTYPE_P, 0},
  383.      {TYPE_END, 0, STATE_ERROR, 0}
  384.      },
  385.     /* 42: STATE_DOCTYPE_P */
  386.     {
  387.      {TYPE_EXACT, (char_t) 'E', STATE_DTD_START, 0},
  388.      {TYPE_END, 0, STATE_ERROR, 0}
  389.      },
  390.     /* 43: STATE_CDATA_BRACKET */
  391.     {
  392.      {TYPE_EXACT, (char_t) 'C', STATE_CDATA_C, 0},
  393.      {TYPE_END, 0, STATE_ERROR, 0}
  394.      },
  395.     /* 44: STATE_CDATA_C */
  396.     {
  397.      {TYPE_EXACT, (char_t) 'D', STATE_CDATA_D, 0},
  398.      {TYPE_END, 0, STATE_ERROR, 0}
  399.      },
  400.     /* 45: STATE_CDATA_D */
  401.     {
  402.      {TYPE_EXACT, (char_t) 'A', STATE_CDATA_A, 0},
  403.      {TYPE_END, 0, STATE_ERROR, 0}
  404.      },
  405.     /* 46: STATE_CDATA_A */
  406.     {
  407.      {TYPE_EXACT, (char_t) 'T', STATE_CDATA_T, 0},
  408.      {TYPE_END, 0, STATE_ERROR, 0}
  409.      },
  410.     /* 47: STATE_CDATA_T */
  411.     {
  412.      {TYPE_EXACT, (char_t) 'A', STATE_CDATA_A2, 0},
  413.      {TYPE_END, 0, STATE_ERROR, 0}
  414.      },
  415.     /* 48: STATE_CDATA_A2 */
  416.     {
  417.      {TYPE_EXACT, (char_t) '[', STATE_CDATA, 0},
  418.      {TYPE_END, 0, STATE_ERROR, 0}
  419.      },
  420. };
  421.  
  422. int range_match (int range, char_t c);
  423. void skip_dtd (parser_state *);
  424. void action (parser_state *, int);
  425.  
  426. void tagname_end (parser_state *parser);
  427. void attrname_end (parser_state *parser);
  428. void attrval_end (parser_state *parser);
  429. void word_end (parser_state *parser);
  430. void ws_end (parser_state *parser);
  431.  
  432. int range_match (int range, char_t c)
  433. {
  434.     int i, r;
  435.  
  436.     r = 0;
  437.     for (i = 0; range_table[range][i].start > 0; i++) {
  438.         if (range_table[range][i].start <= c
  439.             && c <= range_table[range][i].end) {
  440.             r = 1;
  441.         }
  442.     }
  443.     return r;
  444. }
  445.  
  446. void skip_dtd (parser_state *parser)
  447. {
  448.     while (parser->current < parser->maxtext &&
  449.            parser->angleBracketLevel > -1) {
  450.         switch (parser->text[parser->current]) {
  451.         case '<':
  452.             if (parser->squoteLevel == 0 && parser->dquoteLevel == 0)
  453.                 parser->angleBracketLevel++;
  454.             break;
  455.         case '>':
  456.             if (parser->squoteLevel == 0 && parser->dquoteLevel == 0)
  457.                 parser->angleBracketLevel--;
  458.             break;
  459.         case '"':
  460.             if (parser->dquoteLevel > 0)
  461.                 parser->dquoteLevel--;
  462.             else if (parser->squoteLevel == 0)
  463.                 parser->dquoteLevel++;
  464.             break;
  465.         case '\'':
  466.             if (parser->squoteLevel > 0)
  467.                 parser->squoteLevel--;
  468.             else if (parser->dquoteLevel == 0)
  469.                 parser->squoteLevel++;
  470.             break;
  471.         }
  472.         if (parser->angleBracketLevel > -1) parser->current++;
  473.     }
  474. }
  475.  
  476. void tagname_end (parser_state *parser)
  477. {
  478.     parser->pump = 0;
  479.     *(char_t *) (parser->buffer + parser->bcurrent) = 0;
  480.     parser->bcurrent = 0;
  481.     if (parser->element_callback) (parser->element_callback)(parser);
  482. }
  483.  
  484. void attrname_end (parser_state *parser)
  485. {
  486.     parser->pump = 0;
  487.     *(char_t *) (parser->buffer + parser->bcurrent) = 0;
  488.     parser->bcurrent = 0;
  489.     if (parser->attrname_callback) (parser->attrname_callback)(parser);
  490. }
  491.  
  492. void attrval_end (parser_state *parser)
  493. {
  494.     parser->pump = 0;
  495.     *(char_t *) (parser->buffer + parser->bcurrent) = 0;
  496.     parser->bcurrent = 0;
  497.     if (parser->attrval_callback) (parser->attrval_callback)(parser);
  498. }
  499.  
  500. void word_end (parser_state *parser)
  501. {
  502.     parser->pump = 0;
  503.     *(char_t *) (parser->buffer + parser->bcurrent) = 0;
  504.     parser->bcurrent = 0;
  505.     if (parser->word_callback) (parser->word_callback)(parser);
  506. }
  507.  
  508. void ws_end (parser_state *parser)
  509. {
  510.     parser->pump = 0;
  511.     *(char_t *) (parser->buffer + parser->bcurrent) = 0;
  512.     parser->bcurrent = 0;
  513.     if (parser->ws_callback) (parser->ws_callback)(parser);
  514. }
  515.  
  516. void action (parser_state *parser, int variant)
  517. {
  518.     unsigned int action;
  519.     
  520.     action = state_table[parser->state][variant].action;
  521.     if (action & ACTION_TAGNAME_END) tagname_end (parser);
  522.     if (action & ACTION_ATTRNAME_END) attrname_end (parser);
  523.     if (action & ACTION_ATTRVAL_END) attrval_end (parser);
  524.     if (action & ACTION_WORD_END) word_end (parser);
  525.     if (action & ACTION_WS_END) ws_end (parser);
  526.     if (action & ACTION_PUMP_START) parser->pump = 1;
  527. }
  528.  
  529. void tox_parse (parser_state *parser)
  530. {
  531.     char_t c;
  532.     int i, transition;
  533.     
  534.     while (parser->current < parser->maxtext &&
  535.         parser->state != STATE_ERROR && parser->state != STATE_END) {
  536.  
  537.         switch (parser->char_width) {
  538.             case 1: c = *(unsigned char *)(parser->text + parser->current); break;
  539.             case 2: c = *(char_t *) (parser->text + parser->current); break;
  540.             default: c = 0; break;
  541.         }
  542.         
  543.         transition = 0;
  544.         for (i = 0; !transition && parser->state != STATE_ERROR; i++) {
  545.             switch (state_table[parser->state][i].accept_type) {
  546.             case TYPE_EXACT:
  547.                 if ((unsigned int) state_table[parser->state][i].accept_value == (unsigned int) c) {
  548.                     transition = 1;
  549.                     action (parser, i);
  550.                     parser->state = state_table[parser->state][i].next_state;
  551.                 }
  552.                 break;
  553.             case TYPE_RANGE:
  554.                 if (range_match
  555.                     ((int) state_table[parser->state][i].accept_value, c)) {
  556.                     transition = 1;
  557.                     action (parser, i);
  558.                     parser->state = state_table[parser->state][i].next_state;
  559.                 }
  560.                 break;
  561.             case TYPE_SPECIAL:
  562.                 switch ((int) state_table[parser->state][i].accept_value) {
  563.                     case SPECIAL_SKIP_DTD:
  564.                         skip_dtd (parser);
  565.                         transition = 1;
  566.                         if (parser->angleBracketLevel == -1) {
  567.                             parser->state = state_table[parser->state][i].next_state;
  568.                             parser->squoteLevel = 0;
  569.                             parser->dquoteLevel = 0;
  570.                             parser->angleBracketLevel = 0;
  571.                         }
  572.                         break;
  573.                 }
  574.                 break;
  575.             case TYPE_END:
  576.                 parser->state = STATE_ERROR;
  577.                 break;
  578.             }
  579.         }
  580.  
  581.         if (parser->pump && parser->bcurrent < parser->maxbuf) {
  582.             switch (parser->char_width) {
  583.                 case 1: *(unsigned char *) (parser->buffer + parser->bcurrent) =
  584.                     (unsigned char) c; break;
  585.                 case 2: *(char_t *)(parser->buffer + parser->bcurrent) = c;
  586.                     break;
  587.             }
  588.             parser->bcurrent += parser->char_width;
  589.         }
  590.         parser->current += parser->char_width;
  591.     }
  592. }
  593.  
  594. /*
  595.  * Local variables:
  596.  * c-basic-offset: 4
  597.  * tab-width: 4
  598.  * End:
  599.  */
  600.